package com.shinbada.modules.competitor.service;

import com.shinbada.excel.ExcelKit;
import com.shinbada.excel.handler.DefaultExcelReadStrategyHandlerV3;
import com.shinbada.excel.modle.CheckResult;
import com.shinbada.excel.modle.ImportExcelResult;
import com.shinbada.excel.modle.StrategyCheckService;
import com.shinbada.excel.modle.UploadModle;

import java.util.*;

import com.google.common.collect.Maps;

import java.util.stream.Collectors;

import com.shinbada.modules.competitor.entity.CompetitorNoumenonDataItem;
import com.shinbada.modules.competitor.entity.CompetitorProductDataItem;
import lombok.SneakyThrows;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.shinbada.core.persistence.Page;
import com.shinbada.core.service.CrudService;
import com.shinbada.modules.competitor.entity.CompetitorControlDataItem;
import com.shinbada.modules.competitor.mapper.CompetitorControlDataItemMapper;
import org.springframework.web.multipart.MultipartFile;

/**
 * 控制器-数据项Service
 * @author initcap
 * @version 2021-08-05
 */
@Service
@Transactional(readOnly = true)
public class CompetitorControlDataItemService extends CrudService<CompetitorControlDataItemMapper, CompetitorControlDataItem> implements StrategyCheckService<CompetitorControlDataItem> {

    private Map<String, String> keys;

    @Override
	public CompetitorControlDataItem get(String id) {
		return super.get(id);
	}

	@Override
	public List<CompetitorControlDataItem> findList(CompetitorControlDataItem competitorControlDataItem) {
		return super.findList(competitorControlDataItem);
	}

	@Override
	public Page<CompetitorControlDataItem> findPage(Page<CompetitorControlDataItem> page, CompetitorControlDataItem competitorControlDataItem) {
		return super.findPage(page, competitorControlDataItem);
	}

	@Transactional(readOnly = false)
	@Override
	public void save(CompetitorControlDataItem competitorControlDataItem) {
		super.save(competitorControlDataItem);
	}

	@Transactional(readOnly = false)
	@Override
	public void delete(CompetitorControlDataItem competitorControlDataItem) {
		super.delete(competitorControlDataItem);
	}

	@Transactional(readOnly = false)
	@SneakyThrows
    public ImportExcelResult<CompetitorControlDataItem> uploadExcel(MultipartFile file, UploadModle modle) {
		// 1. 准备提前数据
		readExcelInit();
		// 2. 添加数据处理器
		DefaultExcelReadStrategyHandlerV3<CompetitorControlDataItem> excelReadHandler = new DefaultExcelReadStrategyHandlerV3<>(modle, this);
		// 3. 执行导入
		ExcelKit.$Import(CompetitorControlDataItem.class).readXlsx(file.getInputStream(), excelReadHandler);
		// 4. 获得导入结果集
		ImportExcelResult<CompetitorControlDataItem> importExcelResult = excelReadHandler.results();
		// 5. 批量添加成功数据
		importExcelResult.getSuccessList().forEach(this::save);
		// 返回结果,成功的数据不返回了，影响响应速度
		importExcelResult.setSuccessList(null);
		return importExcelResult;

    }

    /**
     * @param entity 实体类
     * @return 这个key的获取决定了，在Excel导入的时候需要校验的唯一标准
     */
    private String getReadExcelKey(CompetitorControlDataItem entity) {
        return entity.getId() + entity.getRemarks();
    }

	private void readExcelInit() {
    	// 获取到现在数据库中的所有数据
    	List<CompetitorControlDataItem> db = mapper.findAllList(new CompetitorControlDataItem());
    	this.keys = Maps.newHashMapWithExpectedSize(db.size());
		// 转换键配置,请根据必要条件实现，直接使用会有问题
        db.forEach(entity -> this.keys.put(getReadExcelKey(entity), entity.getId()));
	}

	@Override
	public CheckResult readAndCheck(CompetitorControlDataItem entity) {
    	// 验证重复数据,请根据必要条件实现，直接使用会有问题
    	String key = getReadExcelKey(entity);
		if (this.keys.containsKey(key)) {
			entity.setId(this.keys.get(key));
			return CheckResult.cover(key);
		}
		// 添加数据
		this.keys.put(key, "");
		return CheckResult.pass(key);
	}

	public List<CompetitorControlDataItem> getDataListByNameAndType(CompetitorProductDataItem competitorProductDataItem) {
		return mapper.getDataListByNameAndType(competitorProductDataItem).stream().collect(
				Collectors.collectingAndThen(Collectors.toCollection(() ->
						new TreeSet<>(Comparator.comparing(CompetitorControlDataItem::getControlValue))), ArrayList::new)
		);
	}
}
